﻿// SMIL is a community project available under the Microsoft Public License (Ms-PL)
// Code is provided as is and with no warrenty – Use at your own risk
// View the project and the latest code at http://smil.codeplex.com/

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using Microsoft.Maps.MapControl;

using System.Windows.Browser;

namespace SMIL.Client.CoordinateXAP
{
    public partial class MainPage : UserControl
    {
        const string _APPKEY = "SMIL.BingMap.CredentialsKey";

        int isMovingIcon = 0;
        int isFinding = 0;
        int isViewing = 0;

        Pushpin pin;
        Point offset;
        string idInBrowserForTextField = string.Empty;
        HtmlDocument doc;

        public string AppKey { get; set; }

        public MainPage()
        {
            InitializeComponent();
            Loaded += new RoutedEventHandler(MainPage_Loaded);      
        }

        void MainPage_Loaded(object sender, RoutedEventArgs e)
        {
            // TO DO
            // Add map.credentials here from web.config
            //

            MouseLeftButtonUp += new MouseButtonEventHandler(MainPage_MouseLeftButtonUp);
            map.MouseMove += map_MouseMove;
            pin = GetPin();
          
            pin.MouseEnter += new MouseEventHandler(pin_MouseEnter);
            pin.MouseLeave += new MouseEventHandler(pin_MouseLeave);
            pin.MouseLeftButtonDown +=new MouseButtonEventHandler(pin_MouseLeftButtonDown);
            findControl.OnAdressFound += new DeepEarth.BingMapsToolkit.Client.Controls.AdressFound(findControl_OnAdressFound);
            
            sPanel.MouseEnter += new MouseEventHandler(sPanel_MouseEnter);
            sPanel.MouseLeave += new MouseEventHandler(sPanel_MouseLeave);
            doc = HtmlPage.Document;
            
            map.CredentialsProvider = new ApplicationIdCredentialsProvider((App.Current.Resources.Contains(_APPKEY)) ? App.Current.Resources[_APPKEY] as string : "");
            
            SetStartCoordinates();
        }

        #region Mouse
        void sPanel_MouseLeave(object sender, MouseEventArgs e)
        {
            if (isViewing == 0)
                VisualStateManager.GoToState(this, "My2ndMouseState", true);
        }

        void sPanel_MouseEnter(object sender, MouseEventArgs e)
        {
            if (isViewing == 0)
                VisualStateManager.GoToState(this, "MyMouseEnter", true);
        }

        #endregion



        private void SetStartCoordinates()
        {
            string coordinates = string.Empty;

            persisted.ViewSet = false;
            string href = doc.GetProperty("url") as string;

            SetIsViewing(href);

            if (isViewing == 1)
            {
                string id = GetTagFromTitle("span", "lCoordinate");
                if (!string.IsNullOrEmpty(id))
                {
                    HtmlElement element = doc.GetElementById(id);
                    coordinates = element.GetProperty("innerHTML") as string;
                }
            }
            else
            {
                idInBrowserForTextField = GetTagFromTitle("span", "lCoordinate");
                idInBrowserForTextField = idInBrowserForTextField.Replace("lCoordinate", "TextField");
                HtmlElement element = doc.GetElementById(idInBrowserForTextField);
                coordinates = element.GetProperty("value").ToString();
            }

            if (string.IsNullOrEmpty(coordinates))
                return;

            double lat;
            double lon;
            double zoom;

            AdjustForCultureOnSetStartCoordinates(coordinates, out lat, out lon, out zoom);

            map.SetView(new Location(lat, lon), zoom);
            persisted.ViewSet = true;

            PlottPushPin(new Location(lat, lon));           

        }

        private void SetIsViewing(string href)
        {
            if (href.Contains("DispForm")) // Display view
            {
                isViewing++;
            }
        }

        string GetTagFromTitle(string tagName, string idPostFix)
        {
            HtmlDocument doc = HtmlPage.Document;
            ScriptObjectCollection objs =  doc.GetElementsByTagName(tagName);

            foreach (var item in doc.GetElementsByTagName(tagName))
            {
                string id = item.GetProperty("id") as string;
                if (id.Contains(idPostFix))
                {
                    return id;
                }
            }

            return null;
        }

        private static void AdjustForCultureOnSetStartCoordinates(string coordinates, out double lat, out double lon, out double zoom)
        {
            System.Globalization.CultureInfo cultureInfo = 
                new System.Globalization.CultureInfo(System.Globalization.CultureInfo.CurrentCulture.Name); 
            cultureInfo.NumberFormat.NumberDecimalSeparator = ".";
            string[] pieces = coordinates.Split(new char[] { ' ', '=' }, StringSplitOptions.RemoveEmptyEntries);
            
            lat = double.Parse(pieces[1].Replace(',', '.'), cultureInfo.NumberFormat);
            lon = double.Parse(pieces[3].Replace(',', '.'), cultureInfo.NumberFormat);
            zoom = double.Parse(pieces[5].Replace(',', '.'), cultureInfo.NumberFormat);
        }

        void UpdateCoordinate(Location location)
        {
            string zoom = Convert.ToInt32(map.ZoomLevel).ToString();

            doc.GetElementById(idInBrowserForTextField).SetProperty("value", "n=" + location.Latitude + 
                " e=" + location.Longitude + " zoom=" + zoom);
        }

        void findControl_OnAdressFound(object sender, DeepEarth.BingMapsToolkit.Client.Controls.GeocodeService.GeocodeResult result)
        {
            isFinding++;
            PlottPushPin(new Location(result.Locations[0].Latitude, result.Locations[0].Longitude));
        }

        #region Pin_MouseEnterLeave
        void pin_MouseLeave(object sender, MouseEventArgs e)
        {
            Cursor = Cursors.Arrow;
        }

        void pin_MouseEnter(object sender, MouseEventArgs e)
        {
            if (isViewing == 0)
                Cursor = Cursors.Hand;
        }
        #endregion

        void MainPage_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
        {
            if (tbMark.IsChecked.GetValueOrDefault(false) || isMovingIcon == 1)
            {
                PlottPushPin(map.ViewportPointToLocation(GetPoint(e)));
                tbMark.IsChecked = false;
                isMovingIcon--;
                Cursor = Cursors.Arrow;
            }
        }

        void pin_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            if (isViewing == 0)
            {
                offset = e.GetPosition(pin);
                isMovingIcon++;
            }
        }

        void map_MouseMove(object sender, MouseEventArgs e)
        {
            if (isMovingIcon == 1)
            {
                map.MousePan += (o, ee) => { o = null; ee.Handled = true; };
                Point point = GetPoint(e);
                PlottPushPin(map.ViewportPointToLocation(GetPoint(e)));
            }
            else
                map.MousePan += (o, ee) => { ee.Handled = false; };
            
        }

        private Point GetPoint(MouseEventArgs e)
        {
            Point point = e.GetPosition(map);
            point.Y += (41 - offset.Y);
            return point;
        }

        void PlottPushPin(Location location)
        {
            if (map.Children != null && map.Children.Count == 0)
            {
                pin = GetPin();
                map.Children.Add(pin);
            }
            pin.Location = location;
            
            if (isFinding == 1)
            {
                map.Center = location;
                isFinding--;
            }
            Dispatcher.BeginInvoke(delegate { UpdateCoordinate(location); });
        }

        Pushpin GetPin()
        {
            if (pin == null)
            {
                pin = new Pushpin();
            }
            return pin;
        }

        private void tbMark_Checked(object sender, RoutedEventArgs e)
        {
            return;
        }

        private void tbMark_Unchecked(object sender, RoutedEventArgs e)
        {
            return;
        }

        private void bFullScreen_Click(object sender, RoutedEventArgs e)
        {
            App.Current.Host.Content.IsFullScreen = !App.Current.Host.Content.IsFullScreen;
        }
    }
}
